SVM实现多分类常用的两种方法以及一对一法的代码(VS13+opencv3.4)

SVM实现多分类常用的两种方法以及一对一法的代码(VS13+opencv3.4)

SVM是一个二值分类器,处理多分类问题的时候需要构造合适的多类分类器。
(1)直接法,直接在目标函数上进行修改,将多个分类面的参数求解合并到一个最优化问题中,通过求解该最优化问题“一次性”实现多类分类。这种方法看似简单,但其计算复杂度比较高,实现起来比较困难,所以没有被广泛应用。
(2)间接法,将多类问题分解为一系列SVM可直接求解的二值分类问题,再根据一系列SVM求解结果得到最终判别结果。基于此种思想的多分类方法有一对余类法,一对一法,DAG法,决策树方法,纠错输出编码法,共五种,下面将说明比较常用的一对余类法,一对一法。

1.一类对余类法(One versus rest,OVR)是最早出现也是目前应用最为广泛的方法之一,其步骤是构造k个两类分类机(假设共有K个类别),训练时第i个分类机取训练集中第i类为正样本,其余类都划分为负样本,进行训练,实例可见下图。判别时,输入信号分别经过k个分类机共得到k个输出值fi(x)=sgn(gi(x)),若只有一个+1出现,则其对应类别为输入信号类别,此为理想情况 ;实际情况下构造的决策函数总是有误差的,若输出不只一个+1(不只一类声称它属于自己),或者没有一个输出为+1(即没有一个类声称它属于自己),则比较g(x)输出值,最大者对应类别为输入的类别。
在这里插入图片描述
图片里面有三类,因此训练三个分类器,三类中的一个类作为正样本,则其它两类都划分为负样本,进行训练,得到三个分类器。

评价:这种方法的优点是,对k类(K较大)问题,只需要训练k个两类分类支持向量机,故其所得到的分类函数的个数(k个)较少,其分类速度相对较快。缺点:样本不平衡问题:一对多方法在训练每个分类器时,其训练样本是1类对k-1类,正负样本的规模相差较大,如1个正样本和99个负样本,则在训练此分类器时很有可能最终的分类器是D(x)=-1,即不论输入什么都输出-1,这样他的错误率也很小只有0.01,达不到训练的效果。解决这个问题可以用一对一方法。详细见博客链接:https://blog.csdn.net/henghane/article/details/54970544

2.一对一法
 分类器个数:假设有K类样本,其做法是在任意两类样本之间设计一个SVM,因此k个类别的样本就需要设计k(k-1)/2个SVM。
结果判定:训练好全部分类器后,当对一个测试样本进行分类时,此样本经过全部分类器,得到k(k-1)/2个分类结果,最后得票最多的类别即为该测试样本的类别。本次将实现基于这个方法的人,车,背景三分类,因为只有三类,所以分类器个数只需要三个。

评价:这种方法虽然好,但是当类别k很多的时候,分类器的个数是k*(k-1)/2,需要多次投票;此外还会存在误判(例如人在车与背景分类器中被划分为背景),拒分(票数相同不知道如何划分类),解决误判,拒分问题可采用DAG法。

3.DAG法
DAG-SvMS是由PIatt提出的决策导向的循环图DAG导出的,是针对“一对一"SvMS存在误分,拒分现象提出的。这种方法的训练过程类似于“一对一”方法,k类别问题需要求解k(k-1)/2个支持向量机分类器,这些分类器构成一个有向无环图。该有向无环图中含有k(k-1)/2个内部节点和k个叶结点,每个节点对应一个二类分类器。
在这里插入图片描述

DAG-SVMS简单易行,只需要使用k一1个决策函数即可得出结果,较“一对一"方法提高了测试速度,而且不存在误分、拒分区域;另外,由于其特殊的结构,故有一定的容错性,分类精度较一般的二叉树方法高。然而,由于存在自上而下的“误差积累”现象是层次结构固有弊端,故DAG-SVMS也逃脱不掉。即如果在

  • 6
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是使用自定义的一对一分类方法进行SVM一对一分类的Python代码实现: ```python import numpy as np from sklearn import svm # 自定义一对一分类方法 class OneVsOneSVM: def __init__(self, classes): self.classes = classes self.classifiers = {} def fit(self, X, y): for i in range(len(self.classes)): for j in range(i+1, len(self.classes)): # 选出当前两个类别的样本 Xi = X[(y == self.classes[i]) | (y == self.classes[j])] yi = y[(y == self.classes[i]) | (y == self.classes[j])] # 将类别i设为1,类别j设为-1 yi[yi == self.classes[i]] = 1 yi[yi == self.classes[j]] = -1 # 训练SVM分类器 clf = svm.SVC(kernel='linear') clf.fit(Xi, yi) # 保存分类器 self.classifiers[(self.classes[i], self.classes[j])] = clf def predict(self, X): # 统计每个类别的得分 scores = {c: 0 for c in self.classes} for i in range(len(self.classes)): for j in range(i+1, len(self.classes)): # 使用分类器预测当前两个类别的得分 clf = self.classifiers[(self.classes[i], self.classes[j])] score = clf.decision_function(X) # 更新得分 scores[self.classes[i]] += np.sum(score > 0) scores[self.classes[j]] += np.sum(score < 0) # 返回得分最高的类别 return max(scores, key=scores.get) # 使用自定义的一对一分类方法进行SVM一对一分类 X = [[0, 0], [1, 1], [0, 1], [1, 0]] y = [0, 0, 1, 1] classes = [0, 1] clf = OneVsOneSVM(classes) clf.fit(X, y) print(clf.predict([[2, 2], [-1, -1]])) # 输出:[0 1] ``` 以上代码中,我们首先定义了一个`OneVsOneSVM`类,该类实现了自定义的一对一分类方法。在`fit`方法中,我们遍历所有可能的类别对,选出当前两个类别的样本,将类别i设为1,类别j设为-1,然后训练SVM分类器,并保存分类器。在`predict`方法中,我们统计每个类别的得分,使用分类器预测当前两个类别的得分,更新得分,最后返回得分最高的类别。 接下来,我们使用一个简单的例子来演示如何使用自定义的一对一分类方法进行SVM一对一分类。在这个例子中,我们有4个样本,每个样本有2个特征,类别分别为0和1。我们首先定义了一个`OneVsOneSVM`对象,然后使用`fit`方法训练模型,最后使用`predict`方法预测新样本的类别。在这个例子中,我们预测了两个新样本的类别,输出为0和1。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值